package cn.tedu.store.admin.webapi.service.impl;

import cn.tedu.store.admin.webapi.mapper.AdminMapper;
import cn.tedu.store.admin.webapi.security.AdminDetails;
import cn.tedu.store.commons.ex.ServiceException;
import cn.tedu.store.commons.pojo.admin.dto.AdminAddNewDTO;
import cn.tedu.store.commons.pojo.admin.dto.AdminLoginDTO;
import cn.tedu.store.commons.pojo.admin.entity.Admin;
import cn.tedu.store.commons.pojo.admin.vo.AdminListItemVO;
import cn.tedu.store.commons.pojo.admin.vo.AdminStandardVO;
import cn.tedu.store.commons.web.ServiceCode;

import cn.tedu.store.admin.service.IAdminService;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {

    @Autowired
    AdminMapper adminMapper;
    @Autowired
    AuthenticationManager authenticationManager;
    @Value("${csmall.jwt.secret-key}")
    String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    long durationInMinute;

    public AdminServiceImpl() {
        log.debug("创建管理员业务实现类: AdminServiceImpl");
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                adminLoginDTO.getUsername(), adminLoginDTO.getPassword());
        Authentication authenticateResult =
                authenticationManager.authenticate(authentication);
        log.debug("执行认证成功,AuthenticationManager{}", authenticateResult);
        Object principal = authenticateResult.getPrincipal();
        log.debug("认证结果中的Principal数据类型：{}", principal.getClass().getName());
        log.debug("认证结果中的Principal数据：{}", principal);
        AdminDetails adminDetails = (AdminDetails) principal;

        log.debug("准备生成jwt数据");
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", adminDetails.getId());
        claims.put("username", adminDetails.getUsername());
        claims.put("authorities", JSON.toJSONString(adminDetails.getAuthorities()));

        Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("返回jwt数据: {}", jwt);
        return jwt;
    }

    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("开始处理添加管理员业务,参数:{}", adminAddNewDTO);
        int countByName = adminMapper.countByName(adminAddNewDTO.getUsername());
        if (countByName != 0) {
            String message = "添加失败,用户名被占用";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        log.debug("准备添加管理员");
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminAddNewDTO, admin);
        adminMapper.insert(admin);
        log.debug("添加管理员成功");
    }

    @Override
    public void delete(Long id) {
        log.debug("开始处理删除管理员业务 参数:{}", id);
        AdminStandardVO adminStandardVO = adminMapper.getStandardById(id);
        if (adminStandardVO == null) {
            String message = "删除管理员失败,未找到相应资源";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        log.debug("准备删除id为{}的管理员", id);
        adminMapper.deleteById(id);
        log.debug("删除管理员成功!");
    }

    @Override
    public void setEnable(Long id) {
        updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }

    @Override
    public List<AdminListItemVO> list() {
        log.debug("开始处理删除管理员业务 参数:无");
        List<AdminListItemVO> list = adminMapper.list();
        log.debug("查询完成,获取到{}条数据", list.size());
        return list;
    }

    private void updateEnableById(Long id, Integer enable) {
        String[] tips = {"禁用", "启用"};
        log.debug("开始处理【{}管理员】的业务，参数：{}", tips[enable], id);

        //判断id是否等于1
        if (id == 1) {
            String message = tips[enable] + "管理员失败,尝试访问的数据不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 检查尝试访问的数据是否存在
        AdminStandardVO queryResult = adminMapper.getStandardById(id);
        if (queryResult == null){
            String message = tips[enable] + "管理员失败,尝试访问的数据不存在!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //判断状态是否冲突
        if (queryResult.getEnable() == enable){
            String message = tips[enable] + "管理员失败,该管理员已经处于" + tips[enable] + "状态!";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //更新管理员数据
        Admin admin = new Admin();
        admin.setId(id);
        admin.setEnable(enable);
        adminMapper.updateById(admin);
    }
}
